home *** CD-ROM | disk | FTP | other *** search
/ 3D GFX / 3D GFX.iso / pcutils / os2 / apple / source / easy.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-31  |  17.7 KB  |  770 lines

  1. #include "easy.h"
  2.  
  3. static int window_invalid=0;
  4. static Window *actwindow;
  5.  
  6. Program program;
  7.  
  8. // ******************* Debug tools **********************
  9.  
  10. void dumplong (long n)
  11. {    char s[256];
  12.     sprintf(s,"%ld, %lx",n,n);
  13.     WinMessageBox(HWND_DESKTOP,HWND_DESKTOP,s,"Dump",0,
  14.         MB_OK);
  15. }
  16.  
  17. void dump (char *s)
  18. {    WinMessageBox(HWND_DESKTOP,HWND_DESKTOP,s,"Dump",0,
  19.         MB_OK);
  20. }
  21.  
  22. // *********** Messages etc. ***************************
  23.  
  24. void Message (char *s, char *title)
  25. {    WinMessageBox(HWND_DESKTOP,HWND_DESKTOP,s,title,0,
  26.         MB_OK|MB_INFORMATION);
  27. }
  28.  
  29. void Warning (char *s, char *title)
  30. {    WinMessageBox(HWND_DESKTOP,HWND_DESKTOP,s,title,0,
  31.         MB_OK|MB_WARNING);
  32. }
  33.  
  34. int Question (char *s, char *title)
  35. {    return (WinMessageBox(HWND_DESKTOP,HWND_DESKTOP,s,title,0,
  36.         MB_YESNO|MB_QUERY)==MBID_YES);
  37. }
  38.  
  39. // **************** Threads **********************
  40.  
  41. void ThreadProc (Thread *s)
  42. {    int ret=s->call();
  43.     DosExit(EXIT_THREAD,ret);
  44. }
  45.  
  46. void Thread::start (Parameter p)
  47. {   stop();
  48.     P=p;
  49.     DosCreateThread(&Tid,(PFNTHREAD)ThreadProc,
  50.         Parameter(this),0,Stacksize);
  51.     Started=1;
  52. }
  53.  
  54. void Thread::stop ()
  55. {    if (Started) DosKillThread(Tid);
  56.     Started=0;
  57. }
  58.  
  59. void Thread::suspend ()
  60. {    if (Started) DosSuspendThread(Tid);
  61. }
  62.  
  63. void Thread::resume ()
  64. {    if (Started) DosResumeThread(Tid);
  65. }
  66.  
  67. void Thread::wait ()
  68. {    if (Started) DosWaitThread(&Tid,DCWW_WAIT);
  69. }
  70.  
  71. // **************** Time *************************
  72.  
  73. void Time::set ()
  74. {    DosQuerySysInfo(QSV_TIME_LOW,QSV_TIME_LOW,
  75.         &Seconds,sizeof(ULONG));
  76. }
  77.  
  78. // ********************* Strings ************************
  79.  
  80. long defaultsize=256;
  81.  
  82. String::String (char *text, LONG size)
  83. {    P=new char[size];
  84.     strcpy(P,text);
  85.     Size=size;
  86. }
  87.  
  88. String::String (int id)
  89. {   char s[1024];
  90.     WinLoadString(program.hab(),NULLHANDLE,id,1022,s);
  91.     Size=strlen(s)+1;
  92.     P=new char[Size];
  93.     strcpy(P,s);
  94. }
  95.  
  96.  
  97. String::String ()
  98. {   Size=defaultsize;
  99.     P=new char[Size];
  100.     *P=0;
  101. }
  102.  
  103. String::~String ()
  104. {    delete P;
  105. }
  106.  
  107. void String::copy (char *text)
  108. {    delete P;
  109.     Size=strlen(text)+1;
  110.     P=new char[Size];
  111.     strcpy(P,text);
  112. }
  113.  
  114. char *String::filename ()
  115. {    char *p=P+strlen(P);
  116.     while (p>P)
  117.     {    if (*p=='\\' || *p==':') return p+1;
  118.         p--;
  119.     }
  120.     return p;
  121. }
  122.  
  123. void String::stripfilename ()
  124. {    *filename()=0;
  125. }
  126.  
  127. // ****************** Rectangle *************************
  128.  
  129. void Rectangle::minsize (LONG wmin, LONG hmin)
  130. {    if (W<0 && -W<wmin) W=-wmin;
  131.     else if (W>=0 && W<wmin) W=wmin;
  132.     if (H<0 && -H<hmin) H=-hmin;
  133.     else if (H>=0 && H<hmin) H=hmin;
  134. }
  135.  
  136. void Rectangle::hrescale (double scale)
  137. {    H=(LONG)(scale*abs(W))*(H<0?-1:1);
  138. }
  139.  
  140. void Rectangle::wrescale (double scale)
  141. {    W=(LONG)(scale*abs(H))*(W<0?-1:1);
  142. }
  143.  
  144. // ******************** Program *************************
  145.  
  146. MRESULT EXPENTRY MainWindowProc (HWND hwnd, ULONG msg,
  147.     MPARAM mp1, MPARAM mp2)
  148. {    Window *window;
  149.     clicktype click;
  150.     if (window_invalid) window=actwindow;
  151.     else window=(Window *)WinQueryWindowPtr(hwnd,QWL_USER);
  152.     POINTS *points;
  153.     switch (msg)
  154.     {   case WM_CREATE :
  155.             window->Handle=hwnd;
  156.             break;
  157.         case WM_PAINT :
  158.             {    RedrawPS ps(hwnd,*window);
  159.                 window->redraw(ps);
  160.             }
  161.             break;
  162.         case WM_SIZE :
  163.             if (SHORT1FROMMP(mp2)==0) goto def;
  164.             if (window->Width==SHORT1FROMMP(mp2) &&
  165.                 window->Height==SHORT2FROMMP(mp2)) goto def;
  166.             window->Width=SHORT1FROMMP(mp2);
  167.             window->Height=SHORT2FROMMP(mp2);
  168.             window->sized();
  169.             break;
  170.         case WM_BUTTON1CLICK :
  171.             click=button1; goto button;
  172.         case WM_BUTTON2CLICK :
  173.             click=button2; goto button;
  174.         case WM_BUTTON3CLICK :
  175.             click=button3; goto button;
  176.         case WM_BUTTON1UP :
  177.             click=button1up; goto button;
  178.         case WM_BUTTON2UP :
  179.             click=button2up; goto button;
  180.         case WM_BUTTON3UP :
  181.             click=button3up; goto button;
  182.         case WM_BUTTON1DOWN :
  183.             click=button1down; goto button;
  184.         case WM_BUTTON2DOWN :
  185.             click=button2down; goto button;
  186.         case WM_BUTTON3DOWN :
  187.             click=button3down; goto button;
  188.         case WM_BUTTON1DBLCLK :
  189.             click=button1double; goto button;
  190.         case WM_BUTTON2DBLCLK :
  191.             click=button2double; goto button;
  192.         case WM_MOUSEMOVE :
  193.             click=mousemove; goto button;
  194.         case WM_BUTTON3DBLCLK :
  195.             click=button3double;
  196.             button: points=(POINTS *)&mp1;
  197.             window->clicked(points->x,points->y,click);
  198.             goto def;
  199.         case WM_COMMAND :
  200.             if (window->Windowmenu)
  201.                 if (window->Windowmenu->call(SHORT1FROMMP(mp1)))
  202.                     break;
  203.             goto def;
  204.         case WM_SHOW :
  205.             window->Visible=SHORT1FROMMP(mp1);
  206.             goto def;
  207.         default :
  208.             def: return WinDefWindowProc(hwnd,msg,mp1,mp2);
  209.     }
  210.     return (MRESULT)FALSE;
  211. }
  212.  
  213. Program::Program ()
  214. {    Hab=WinInitialize(0);
  215.     Hmq=WinCreateMsgQueue(Hab,0);
  216.     WinRegisterClass(Hab,"MainWindow",MainWindowProc,
  217.         CS_SIZEREDRAW,sizeof(Window *));
  218. }
  219.  
  220. Program::~Program ()
  221. {    WinDestroyMsgQueue(Hmq);
  222.     WinTerminate(Hab);
  223. }
  224.  
  225. inline int Program::getmessage ()
  226. {    return WinGetMsg(Hab,&Qmsg,0L,0,0);
  227. }
  228.  
  229. inline void Program::dispatch ()
  230. {    WinDispatchMsg(Hab,&Qmsg);
  231. }
  232.  
  233. void Program::loop ()
  234. {    while(getmessage())
  235.         dispatch();
  236. }
  237.  
  238. Window::Window (int id, char *name, ULONG flags)
  239. {    Id=id; Name=new String(name); Flags=flags;
  240. }
  241.  
  242. void Window::init ()
  243. {   window_invalid=1;
  244.     actwindow=this;
  245.     FrameHandle=WinCreateStdWindow(HWND_DESKTOP,
  246.         WS_VISIBLE,&Flags,"MainWindow",
  247.         Name->text(),WS_VISIBLE,(HMODULE)0,Id,&Handle);
  248.     WinSetWindowPtr(Handle,QWL_USER,this);
  249.     window_invalid=0;
  250.     Windowmenu=NULL;
  251.     Visible=1;
  252.     Width=Height=0;
  253. }
  254.  
  255. Window::~Window ()
  256. {    WinDestroyWindow(FrameHandle);
  257. }
  258.  
  259. void Window::size (LONG w, LONG h)
  260. {   RECTL r;
  261.     r.xLeft=r.yBottom=0; r.xRight=w; r.yTop=h;
  262.     WinCalcFrameRect(FrameHandle,&r,FALSE);
  263.     WinSetWindowPos(FrameHandle,NULLHANDLE,0,0,
  264.         r.xRight,r.yTop,SWP_SIZE);
  265. }
  266.  
  267. void Window::top ()
  268. {    WinSetWindowPos(FrameHandle,
  269.         HWND_TOP,0,0,0,0,SWP_ZORDER);
  270.     WinSetFocus(HWND_DESKTOP,Handle);
  271. }
  272.  
  273. int Window::rubberbox (LONG x, LONG y, clicktype click,
  274.     Rectangle &R, LONG wmin, LONG hmin, double wscale, double hscale)
  275. {   WindowPS ps(*this);
  276.     ps.mix(FM_XOR);
  277.     switch (click)
  278.     {    case button1down :
  279.             Rubber=1;
  280.             R=Rectangle(x,y,wmin,hmin);
  281.             ps.frame(R,0,CLR_GREEN);
  282.             return RUBBER_START;
  283.         case mousemove :
  284.             if (!Rubber) break;
  285.             ps.frame(R,0,CLR_GREEN);
  286.             R.resize(x-R.x(),y-R.y());
  287.             R.minsize(hmin,wmin);
  288.             if (wscale>0) R.wrescale(wscale);
  289.             if (hscale>0) R.hrescale(hscale);
  290.             ps.frame(R,0,CLR_GREEN);
  291.             Rubber=2;
  292.             break;
  293.         case button1up :
  294.             if (!Rubber || Rubber==1) return RUBBER_CANCEL;
  295.             ps.frame(R,0,CLR_GREEN);
  296.             Rubber=0;
  297.             if (abs(y-R.y())>=hmin) return RUBBER_DONE;
  298.             else return RUBBER_CANCEL;
  299.     }
  300.     return RUBBER_ZERO;
  301. }
  302.  
  303. // ************* Menus ************************************
  304.  
  305. Menu::~Menu ()
  306. {    while (Mp)
  307.     {    delete Mp;
  308.         Mp=Mp->next();
  309.     }
  310. }
  311.  
  312. int Menu::call (int command)
  313. {    Menuentry *m=Mp;
  314.     while (m)
  315.         if (m->command()==command)
  316.         {    m->call(command);
  317.             return 1;
  318.         }
  319.         else m=m->next();
  320.     return 0;
  321. }
  322.  
  323. // ************* Presentation Space class (PS) *************
  324.  
  325. void PS::setcolor (int index, Rgb rgb, int pure)
  326. {    LONG table[1];
  327.     table[0]=rgb;
  328.     GpiCreateLogColorTable(Handle,pure?LCOL_PURECOLOR:0,
  329.                 LCOLF_CONSECRGB,index,1,(PLONG)table);
  330. }
  331.  
  332. void PS::directcolor (int pure)
  333. {    GpiCreateLogColorTable(Handle,pure?LCOL_PURECOLOR:0,
  334.                 LCOLF_RGB,0,0,NULL);
  335. }
  336.  
  337. void PS::defaultcolors ()
  338. {    GpiCreateLogColorTable(Handle,LCOL_RESET,0,0,0,NULL);
  339. }
  340.  
  341. void PS::move (LONG c, LONG r, ULONG col)
  342. {   color(col);
  343.     P.x=c; P.y=r; GpiMove(Handle,&P);
  344. }
  345.  
  346. void PS::linerel (LONG w, LONG h, ULONG col)
  347. {   color(col);
  348.     P.x+=w; P.y+=h; GpiLine(Handle,&P);
  349. }
  350.  
  351. void PS::lineto (LONG c, LONG r, ULONG col)
  352. {   color(col);
  353.     P.x=c; P.y=r; GpiLine(Handle,&P);
  354. }
  355.  
  356. void PS::point (LONG c, LONG r, ULONG col)
  357. {   color(col);
  358.     P.x=c; P.y=r; GpiSetPel(Handle,&P);
  359. }
  360.  
  361. void PS::text (char *s, ULONG col, ULONG al)
  362. {    color(col);
  363.     alignment(al);
  364.     GpiCharString(Handle,strlen(s),s);
  365. }
  366.  
  367. void PS::frame (LONG w, LONG h, int r, ULONG col)
  368. {    color(col);
  369.     P.x+=w+1; P.y+=h+1; GpiBox(Handle,DRO_OUTLINE,&P,r,r);
  370. }
  371.  
  372. void PS::area (LONG w, LONG h, int r, ULONG col)
  373. {    color(col);
  374.     GpiSetBackMix(Handle,BM_OVERPAINT);
  375.     GpiSetPattern(Handle,PATSYM_SOLID);
  376.     P.x+=w+1; P.y+=h+1; GpiBox(Handle,DRO_FILL,&P,r,r);
  377. }
  378.  
  379. void PS::framedarea (LONG w, LONG h, int r, ULONG col)
  380. {    color(col);
  381.     GpiSetBackMix(Handle,BM_OVERPAINT);
  382.     GpiSetPattern(Handle,PATSYM_BLANK);
  383.     P.x+=w+1; P.y+=h+1; GpiBox(Handle,DRO_OUTLINEFILL,&P,r,r);
  384. }
  385.  
  386. void PS::frame (Rectangle &R, int r, ULONG col)
  387. {    move(R.x1(),R.y1());
  388.     frame(abs(R.w()),abs(R.h()),r,col);
  389. }
  390.  
  391. void PS::area (Rectangle &R, int r, ULONG col)
  392. {    move(R.x1(),R.y1());
  393.     area(abs(R.w()),abs(R.h()),r,col);
  394. }
  395.  
  396. void PS::framedarea (Rectangle &R, int r, ULONG col)
  397. {    move(R.x1(),R.y1());
  398.     framedarea(abs(R.w()),abs(R.h()),r,col);
  399. }
  400.  
  401. //************ Bitmaps Presentation Spaces *****************
  402.  
  403. BitmapPS::BitmapPS (Window &window)
  404. {    PSZ pszData[4]={"Display",NULL,NULL,NULL};
  405.     BITMAPINFOHEADER2 bmp;
  406.     LONG alData[2],size;
  407.     DeviceHandle=DevOpenDC(program.hab(),OD_MEMORY,"*",4,
  408.         (PDEVOPENDATA)pszData,NULLHANDLE);
  409.     S.cx=window.width(); S.cy=window.height();
  410.     Handle=GpiCreatePS(program.hab(),DeviceHandle,&S,
  411.         PU_PELS|GPIA_ASSOC|GPIT_MICRO);
  412.     GpiQueryDeviceBitmapFormats(Handle,2,(PLONG)alData);
  413.     bmp.cbFix=(ULONG)sizeof(BITMAPINFOHEADER2);
  414.     bmp.cx=S.cx; bmp.cy=S.cy;
  415.     Planes=bmp.cPlanes=alData[0];
  416.     Colorbits=bmp.cBitCount=alData[1];
  417.     bmp.ulCompression=BCA_UNCOMP;
  418.     bmp.cbImage=(((S.cx*(1<<bmp.cPlanes)*(1<<bmp.cBitCount))+31)
  419.         /32)*S.cy;
  420.     bmp.cxResolution=70; bmp.cyResolution=70;
  421.     bmp.cclrUsed=2; bmp.cclrImportant=0;
  422.     bmp.usUnits=BRU_METRIC; bmp.usReserved=0;
  423.     bmp.usRecording=BRA_BOTTOMUP; bmp.usRendering=BRH_NOTHALFTONED;
  424.     bmp.cSize1=0; bmp.cSize2=0;
  425.     bmp.ulColorEncoding=BCE_RGB; bmp.ulIdentifier=0;
  426.     size=sizeof(BITMAPINFO2)+
  427.         (sizeof(RGB2)*(1<<bmp.cPlanes)*(1<<bmp.cBitCount));
  428.     if (DosAllocMem((PVOID *)&Info,size,PAG_COMMIT|PAG_READ|PAG_WRITE))
  429.     {    Valid=0;
  430.         GpiDestroyPS(Handle);
  431.         DevCloseDC(DeviceHandle);
  432.     }
  433.     else Valid=1;
  434.     Info->cbFix=bmp.cbFix;
  435.     Info->cx=bmp.cx; Info->cy=bmp.cy;
  436.     Info->cPlanes=bmp.cPlanes; Info->cBitCount=bmp.cBitCount;
  437.     Info->ulCompression=BCA_UNCOMP;
  438.     Info->cbImage=((S.cx+31)/32)*S.cy;
  439.     Info->cxResolution=70; Info->cyResolution=70;
  440.     Info->cclrUsed=2; Info->cclrImportant=0;
  441.     Info->usUnits=BRU_METRIC;
  442.     Info->usReserved=0;
  443.     Info->usRecording=BRA_BOTTOMUP;
  444.     Info->usRendering=BRH_NOTHALFTONED;
  445.     Info->cSize1=0; Info->cSize2=0;
  446.     Info->ulColorEncoding=BCE_RGB; Info->ulIdentifier=0;
  447.     BitmapHandle=GpiCreateBitmap(Handle,&bmp,FALSE,NULL,Info);
  448.     GpiSetBitmap(Handle,BitmapHandle);
  449.     GpiErase(Handle);
  450. }
  451.  
  452. BitmapPS::~BitmapPS ()
  453. {   if (!Valid) return;
  454.     GpiDeleteBitmap(BitmapHandle);
  455.     DosFreeMem(Info);
  456.     GpiDestroyPS(Handle);
  457.     DevCloseDC(DeviceHandle);
  458. }
  459.  
  460. void BitmapPS::copy (PS &ps)
  461. {    POINTL a[4];
  462.     RECTL r;
  463.     r.xLeft=a[0].x=0; r.yBottom=a[0].y=0;
  464.     r.xRight=a[1].x=S.cx; r.yTop=a[1].y=S.cy;
  465.     a[2].x=0; a[2].y=0; a[3].x=S.cx; a[3].y=S.cy;
  466.     if (!GpiRectVisible(ps.handle(),&r)) return;
  467.     GpiBitBlt(ps.handle(),Handle,4,a,ROP_SRCCOPY,BBO_IGNORE);
  468. }
  469.  
  470. void BitmapPS::save (char *filename)
  471. {    FILE *f;
  472.     BITMAPFILEHEADER2 bfh;
  473.     char *buffer;
  474.     PBITMAPINFO2 pbmi;
  475.     long size,colorsize,hdsize=20;
  476.     ULONG compression=BCA_UNCOMP;
  477.     f=fopen(filename,"wb");
  478.     if (!f)
  479.     {   Warning("Could not open\nthat file.","Save Error");
  480.         return;
  481.     }
  482.     bfh.usType=BFT_BMAP;
  483.     colorsize=((Colorbits<=8)?(1<<Colorbits):256)*sizeof(RGB2);
  484.     size=((width()*Colorbits+31)/32)*4*height();
  485.     bfh.offBits=14+hdsize+colorsize;
  486.     bfh.cbSize=14+hdsize+colorsize+size;
  487.     buffer=(char *)malloc(size);
  488.     pbmi=(PBITMAPINFO2)malloc(16+colorsize);
  489.     memset(pbmi,0,sizeof(BITMAPINFOHEADER2));
  490.     pbmi->cbFix=hdsize;
  491.     pbmi->cPlanes=1;
  492.     pbmi->cBitCount=Colorbits;
  493.     pbmi->ulCompression=compression;
  494.     if (GpiQueryBitmapBits(handle(),0,height(),buffer,pbmi)!=height())
  495.     {   Warning("Bitmap Save Error!","Error");
  496.         goto end;
  497.     }
  498.     fwrite((char *)&bfh,14,1,f);
  499.     fwrite((char *)pbmi,hdsize+colorsize,1,f);
  500.     fwrite(buffer,1,size,f);
  501.     end: free(pbmi);
  502.     free(buffer);
  503.     fclose(f);
  504. }
  505.  
  506. //******************* Fonts ********************************
  507.  
  508. Font::Font (PS &ps)
  509. {   Ps=&ps;
  510.     Fm=(FONTMETRICS *)malloc(sizeof(FONTMETRICS));
  511.     GpiQueryFontMetrics(Ps->handle(),sizeof(FONTMETRICS),Fm);
  512. }
  513.  
  514. Font::Font ()
  515. {    Ps=NULL; Fm=NULL;
  516. }
  517.  
  518. Font::~Font ()
  519. {    if (Fm) free(Fm);
  520. }
  521.  
  522. void Font::set (PS &ps)
  523. {   Ps=&ps;
  524.     if (Fm) free(Fm);
  525.     Fm=(FONTMETRICS *)malloc(sizeof(FONTMETRICS));
  526.     GpiQueryFontMetrics(Ps->handle(),sizeof(FONTMETRICS),Fm);
  527. }
  528.  
  529.  
  530. void Font::text (int c, int r, char *s, ULONG col)
  531. // Draw a Text at char column and row
  532. {    Ps->move(c*wbox(),Ps->height()-r*hbox()-above());
  533.     Ps->text(s,col);
  534. }
  535.  
  536. void Font::centertext (int c, int r, int w, char *s, ULONG col)
  537. // Draw a Text at char column and row
  538. {    Ps->move((2*c+w)*wbox()/2,Ps->height()-r*hbox()-above());
  539.     Ps->text(s,col,TA_CENTER);
  540. }
  541.  
  542. void Font::righttext (int c, int r, int w, char *s, ULONG col)
  543. // Draw a Text at char column and row
  544. {    Ps->move((c+w)*wbox(),Ps->height()-r*hbox()-above());
  545.     Ps->text(s,col,TA_RIGHT);
  546. }
  547.  
  548. void Font::textframe (int c, int r, int w, int h, int rad,
  549.     ULONG col, int framed)
  550. // Draw a frame around a text area
  551. {    Ps->move(c*wbox()-wbox()/2,Ps->height()-(r+h+1)*hbox()+hbox()/2);
  552.     if (framed) Ps->framedarea((w+1)*wbox(),(h+1)*hbox(),rad,col);
  553.     else Ps->area((w+1)*wbox(),(h+1)*hbox(),rad,CLR_WHITE);
  554. }
  555.  
  556. int Font::inframe (int c, int r, int w, int h, LONG x, LONG y)
  557. {    LONG c1,c2,r1,r2;
  558.     c1=c*wbox()-wbox()/2; c2=c1+(w+1)*wbox();
  559.     r1=Ps->height()-(r+h+1)*hbox()+hbox()/2; r2=r1+(h+1)*hbox();
  560.     return (x>c1 && x<c2 && y>r1 && y<r2);
  561. }
  562.  
  563. void Font::getframe (int c, int r, int w, int h,
  564.     LONG &x1, LONG &y1, LONG &x2, LONG &y2)
  565. {    x1=c*wbox()-wbox()/2; x2=x1+(w+1)*wbox();
  566.     y1=Ps->height()-(r+h+1)*hbox()+hbox()/2; y2=y1+(h+1)*hbox();
  567. }
  568.  
  569. int Font::line (int r, int h, LONG y)
  570. {    return (Ps->height()-r*hbox()-y)/hbox();
  571. }
  572.  
  573. // *********************** Text Box **************************
  574.  
  575. void Textbox::redraw ()
  576. {   char *p=Text,*q,c;
  577.     int line=0;
  578.     if (!*F) return;
  579.     F->textframe(X,Y,W,H,Rad,Color,Framed);
  580.     while (1)
  581.     {   q=p; while (*q && *q!='\n') q++;
  582.         c=*q; *q=0;
  583.         switch (Justify)
  584.         {   case text_left : F->text(X,Y+line,p,Color); break;
  585.             case text_right : F->righttext(X,Y+line,W,p,Color); break;
  586.             default : F->centertext(X,Y+line,W,p,Color); break;
  587.         }
  588.         if (!c) break;
  589.         *q=c;
  590.         p=q+1;
  591.         line++;
  592.     }
  593. }
  594.  
  595. //******************* Help ******************************
  596.  
  597. Help::Help (Window &window, int id, char *filename, char *title)
  598. {    HELPINIT hini;
  599.     hini.cb=sizeof(HELPINIT);
  600.     hini.ulReturnCode=0L;
  601.     hini.pszTutorialName=(PSZ)NULL;
  602.     hini.phtHelpTable=
  603.         (PHELPTABLE)MAKELONG(id,0xFFFF);
  604.     hini.hmodHelpTableModule=(HMODULE)0;
  605.     hini.hmodAccelActionBarModule=(HMODULE)0;
  606.     hini.idAccelTable=0;
  607.     hini.idActionBar=0;
  608.     hini.pszHelpWindowTitle=title;
  609.     hini.fShowPanelId = CMIC_HIDE_PANEL_ID;
  610.     hini.pszHelpLibraryName=filename;
  611.     Handle=WinCreateHelpInstance(program.hab(),&hini);
  612.     if (!Handle) { Valid=0; return; }
  613.     Valid=1;
  614.     WinAssociateHelpInstance(Handle,window.framehandle());
  615. }
  616.  
  617. // ****************** Dialogs *************************
  618.  
  619. Dialog *activedlg;
  620.  
  621. static MRESULT EXPENTRY dialogproc (HWND hwnd, ULONG msg,
  622.     MPARAM mp1, MPARAM mp2)
  623. {   Dialogitem *item=activedlg->Items;
  624.     switch (msg)
  625.     {   case WM_INITDLG :
  626.             activedlg->Handle=hwnd;
  627.             while (item)
  628.             {    item->init();
  629.                 item=item->next();
  630.             }
  631.             activedlg->start();
  632.             break;
  633.         case WM_COMMAND :
  634.             activedlg->Result=(SHORT1FROMMP(mp1));
  635.             if (activedlg->handler(SHORT1FROMMP(mp1)))
  636.             {    while (item)
  637.                 {    item->exit();
  638.                     item=item->next();
  639.                 }
  640.                 activedlg->stop();
  641.                 WinDismissDlg(hwnd,SHORT1FROMMP(mp1));
  642.             }
  643.             break;
  644.         default :
  645.             return WinDefDlgProc(hwnd,msg,mp1,mp2);
  646.     }
  647.     return (MRESULT)FALSE;
  648. }
  649.  
  650. Dialog::Dialog (Window &window, int id) : S()
  651. {    W=&window;
  652.     Id=id;
  653.     Items=0;
  654. }
  655.  
  656. Dialogitem *Dialog::entry (Dialogitem *item)
  657. {    Dialogitem *note=Items;
  658.     Items=item;
  659.     return note;
  660. }
  661.  
  662. void Dialog::carryout ()
  663. {   activedlg=this;
  664.     Handle=WinDlgBox(HWND_DESKTOP,W->handle(),dialogproc,
  665.         (HMODULE)0,Id,NULL);
  666. }
  667.  
  668. int Dialog::handler (int com)
  669. {    if (com==DID_OK) return 1;
  670.     return 0;
  671. }
  672.  
  673. char *Dialog::gettext (int id, char *text, long size)
  674. {   HWND handle=WinWindowFromID(Handle,id);
  675.     WinQueryWindowText(handle,size,text);
  676.     return text;
  677. }
  678.  
  679. char *Dialog::gettext (int id)
  680. {   HWND handle=WinWindowFromID(Handle,id);
  681.     WinQueryWindowText(handle,S.size(),(PSZ)S.text());
  682.     return S;
  683. }
  684.  
  685. void Dialog::settext (int id, char *text)
  686. {    HWND handle=WinWindowFromID(Handle,id);
  687.     WinSetWindowText(handle,text);
  688. }
  689.  
  690. MRESULT Dialog::message (int id, int msg,
  691.     Parameter mp1, Parameter mp2)
  692. {    HWND h;
  693.     h=WinWindowFromID(Handle,id);
  694.     return WinSendMsg(h,msg,mp1,mp2);
  695. }
  696.  
  697. //*************** Dialog Items ******************
  698.  
  699. Dialogitem::Dialogitem (int id, Dialog &dialog)
  700. {    Id=id;
  701.     D=&dialog;
  702.     Next=dialog.entry(this);
  703. }
  704.  
  705. void StringItem::init ()
  706. {    D->settext(Id,S);
  707. }
  708.  
  709. void StringItem::exit ()
  710. {    S.copy(D->gettext(Id));
  711. }
  712.  
  713. void DoubleItem::init ()
  714. {    sprintf(S,"%-0.10g",X);
  715.     D->settext(Id,S);
  716. }
  717.  
  718. void DoubleItem::exit ()
  719. {     S.copy(D->gettext(Id));
  720.     sscanf(S,"%lg",&X);
  721. }
  722.  
  723. void LongItem::init ()
  724. {    sprintf(S,"%-ld",N);
  725.     D->settext(Id,S);
  726. }
  727.  
  728. void LongItem::exit ()
  729. {     S.copy(D->gettext(Id));
  730.     sscanf(S,"%ld",&N);
  731. }
  732.  
  733. void SpinItem::init ()
  734. {    D->message(Id,SPBM_SETLIMITS,Upper,Lower);
  735.     D->message(Id,SPBM_SETCURRENTVALUE,N);
  736. }
  737.  
  738. void SpinItem::exit ()
  739. {    D->message(Id,SPBM_QUERYVALUE,&N,Parameter(0,SPBQ_ALWAYSUPDATE));
  740. }
  741.  
  742. //******************* File Selector ********************
  743.  
  744. FileSelector::FileSelector (Window &window,
  745.         char *filter, int saving,
  746.         char *title, char *ok) : Filter(filter)
  747.  
  748. {    memset(&Fd,0,sizeof(FILEDLG));
  749.  
  750.     Fd.cbSize=sizeof(FILEDLG);
  751.     Fd.fl=FDS_CENTER|FDS_ENABLEFILELB
  752.         |(saving?FDS_SAVEAS_DIALOG:FDS_OPEN_DIALOG);
  753.     Fd.pszTitle=title;
  754.     if (!ok)
  755.     {    if (saving) ok="Save";
  756.  
  757.         else ok="Load";
  758.  
  759.     }
  760.  
  761.     Fd.pszOKButton=ok;
  762.     W=&window;
  763.  
  764. }
  765.  
  766.  
  767. char *FileSelector::select ()
  768.  
  769. {   char *p=Filter.filename();
  770.  
  771.     String s(Fd.szFullFile,256);
  772.  
  773.     s.stripfilename();
  774.  
  775.     strcpy(Fd.szFullFile,s); strcat(Fd.szFullFile,p);
  776.  
  777.     Freturn=WinFileDlg(HWND_DESKTOP,W->handle(),&Fd);
  778.  
  779.     if (!Freturn || Fd.lReturn!=DID_OK) return 0;
  780.     return Fd.szFullFile;
  781.  
  782. }
  783.  
  784.